package encrydecry

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/hex"
)

type EncryDecry struct {
	secret string
}

// 主要用于配置加解密，secret必须8字节
func NewEncryDecry(secret string) EncryDecry {
	return EncryDecry{secret: secret}
}

func (o EncryDecry) Encryption(str string) string {
	if len(str) < 1 {
		return ""
	}
	b, err := Encode([]byte(str), o.secret)
	if err != nil {
		return ""
	}
	return hex.EncodeToString(b)
}

func (o EncryDecry) Decryption(str string) string {
	if len(str) < 1 {
		return ""
	}
	b, err := hex.DecodeString(str)
	if err != nil {
		return ""
	}
	ret, err := Decode(b, o.secret)
	if err != nil {
		return ""
	}
	return string(ret)
}

func Encode(data []byte, key string) ([]byte, error) {
	var result []byte
	var err error
	keyByte := []byte(key)
	if block, e := des.NewCipher(keyByte); nil != e {
		err = e
	} else {
		d := pkcs7Padding(data, block.BlockSize())
		iv := keyByte
		mode := cipher.NewCBCEncrypter(block, iv)
		result = make([]byte, len(d))
		mode.CryptBlocks(result, d)
	}

	return result, err
}
func Decode(data []byte, key string) ([]byte, error) {
	var err error
	var result []byte
	keyByte := []byte(key)
	if block, e := des.NewCipher(keyByte); nil != e {
		err = e
	} else {
		iv := keyByte
		mode := cipher.NewCBCDecrypter(block, iv)
		result = make([]byte, len(data))
		mode.CryptBlocks(result, data)
		result = pkcs7UnPadding(result)
	}

	return result, err
}

func pkcs7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

func pkcs7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize // 需要填充的数目
	// 只要少于256就能放到一个byte中，默认的blockSize=16(即采用16*8=128, AES-128长的密钥)
	// 最少填充1个byte，如果原文刚好是blocksize的整数倍，则再填充一个blocksize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding) // 生成填充的文本
	return append(ciphertext, padtext...)
}
